// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rbchat.sqlite;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

import com.x52im.rbchat.MyApplication;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;

import java.util.Vector;

/**
 * 本系统中sqlLite表对象根类，本系统中的表操作对象推荐继承本类后再实现自已的逻辑.<br>
 * 
 * 本类中提供了一个字段用于标识当前数据行数并自行维护之，另提供一字段表示本表最近一次数据插入时间.
 * 
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @since 2.5
 */
public abstract class TableRoot
{
//	/** 主要用于缓存列表查看面板中：本字段表示子类实现的表数据最近更新时间 */
//	protected Date updateTime;
	
	/** 操作子类实现表的context的实例引用 */
	protected Context context;
	/** 子类实现表对应的数据数操作辅助对象实例引用 */
	protected MyDataBase db;
	
	public TableRoot(Context context)
	{
		this.context = context;
	}
	
	/**
	 * 用于插入一行数据到本表中。
	 * 本方法应由子类实现，默认什么也不做，返回-1值。
	 * 
	 * @param rowValues 要插入本表的数据行vector，每个单元的意义及如何使用由子类自行决定
	 * @return 参见：SQLiteDatabase{@link #insert(String, String, ContentValues)}
	 */
	public long insertRow(Vector rowValues)
	{
		return -1;
	}
	
	/**
	 * <p>
	 * 将指定2维护vector表示的多行数据插入到本表中.<br><br>
	 * 
	 * 本方法中在插入开始前开始事务，在数据插入后提交数据以提高性能，否则性
	 * 能将相差N个数量级。要取消事务方式提交只需要把insertRow(..)前后有有关事务操作语句删除即可.<br><br>
	 * </p>
	 * 
	 * @param vector
	 * @see #insertRow(Vector)
	 */
	public void insertRows(Vector<Vector> vector)
	{
		SQLiteDatabase dbImpl = db.getDb(true);
		//* 手动设置开始事务[事务操作语句 1/3]
		dbImpl.beginTransaction();        
		
//		//更新最近刷新时间
//		updateTime = new Date();
		
		//数据插入操作循环
		for(Vector rowVec:vector)
			insertRow(rowVec);
		
		//* 设置事务处理成功，不设置会自动回滚不提交[事务操作语句 2/3]
		dbImpl.setTransactionSuccessful(); 
		//* 事务结束，处理完成 [事务操作语句 3/3]
		dbImpl.endTransaction();        
	}
	
//	/**
//	 * 用于缓存列表查看面板中：返回本表的基本信息，便于查看和管理sqlLite缓存。
//	 * 
//	 * @return 返回的是key、value键值对，键由 {@link #IDENT_TABLE_ID}等定义
//	 * @see #getID()
//	 * @see #getTableName()
//	 * @see #getTableDesc()
//	 */
//	public Map<String,String> getTableInfo()
//	{
//		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//		HashMap tableMap=new HashMap<String,String>();
//		tableMap.put(IDENT_TABLE_ID, getID());//DataBaseHelper.UPDATE_TABLE_SCKH);
//		tableMap.put(IDENT_TABLE_NAME, getTableName());//TABLE_NAME);
//		tableMap.put(IDENT_TABLE_SHOWNAME, getTableDesc());//"商超客户信息数据缓存");
//		tableMap.put(IDENT_TABLE_DATA_COUNT, count+"");
//		tableMap.put(IDENT_TABLE_UPDATE_TIME, sdf.format(updateTime));
//		return tableMap;		
//	}
	
//	/** 
//	 * 返回用于标识本表的唯一id常量值，常量值在 DataBaseHelper中被定义。
//	 * 子类需要实现之.
//	 * 
//	 * @see #getTableInfo() 
//	 */
//	public abstract int getID();
//	/** 
//	 * 返回本表的描述信息。
//	 * 子类需要实现之.
//	 * 
//	 * @see #getTableInfo() 
//	 */
//	public abstract String getTableDesc();
	/** 
	 * 返回本表对应的sqlLite数据库中的表名。
	 * 子类需要实现之.
	 */
	public abstract String getTableName();
	
	/**
	 * 删除本表中的所有数据。
	 */
	public boolean deleteDatas()
	{
//		count = 0;
		return db.getDb(true).delete(getTableName(), null, null)>0;
	}
	
	/**
	 * 初始化数据库操作辅助类，在操作本类中的所有数据库操作方法前必须确保首先调用本方法至少一次。
	 * 
	 * @throws SQLException
	 */
	public void open() throws SQLException
	{
//		if(db == null)
			db = MyDataBase.open(context);
	}
	
	/**
	 * 释放数据库操作辅助类所占用资源，在操作本类中的所有数据库操作方法完成后请显示调用本方法1次，以
	 * 释放资源，一般情况下它将与 {@link #open()}方法成对出现 。
	 * 
	 * @throws SQLException
	 */
	public void close()
	{
		if(db != null)
			db.close();
//		db = null;
	}
	
	/**
	 * 查询本表中的数据.
	 * 
	 * @param fieldNames 要查询的字段名
	 * @param filterSQL 过滤条件
	 * @return
	 * @see SQLiteDatabase #query(String, String[], String, String[], String, String, String, String)
	 */
	public Cursor query(String[] fieldNames, String filterSQL)
	{
		return db.getDb(false).query(getTableName()
				, fieldNames, filterSQL, null, null, null, null);
	}
	
	/**
	 * 插入1行数据到本表中.
	 * 
	 * @param table
	 * @param nullColumnHack
	 * @param values
	 * @return
	 * @see SQLiteDatabase#insert(String, String, ContentValues)
	 */
	public long insert(String table, String nullColumnHack, ContentValues values)
	{
//		count++;
		return db.getDb(true).insert(table, nullColumnHack, values);
	}
	
	/**
	 * 删除表数据.
	 * 
	 * @param table
	 * @param where
	 * @return
	 * @see SQLiteDatabase#delete(String, String, String[])
	 */
	public long delete(String table, String where)
	{
		long efeectRow = db.getDb(true).delete(table, where, null);
//		count = count - efeectRow;
		return efeectRow;
	}
	
	/**
	 * 更新表数据.
	 * 
	 * @param table
	 * @param values
	 * @param whereClause
	 * @return the number of rows affected
	 * @see SQLiteDatabase#update(String, ContentValues, String, String[])
	 */
	public long update(String table, ContentValues values, String whereClause)
	{
		long efeectRow = db.getDb(true).update(table, values, whereClause, null);
		return efeectRow;
	}

	/**
	 * 返回本地用户uid的方便方法。
	 *
	 * @return 如果成功则返回uid，否则返回null
	 */
	public String getLocalUserUid(){
		RosterElementEntity localRee = MyApplication.getInstance(context).getIMClientManager().getLocalUserInfo();
		if (localRee != null){
			return localRee.getUser_uid();
		}
		return null;
	}
	
//	/**
//	 * 用于方法 {@link #refreshDataFromServer()}从服务端取数据时的完整SQL语句。
//	 * 子类必须要实现本方法方可正确使用 {@link #refreshDataFromServer()}，默认本方法只返回空字符串.
//	 * 
//	 * @return 用于方法 {@link #refreshDataFromServer()}从服务端取数据时的完整SQL语句
//	 */
//	protected String getRefreshDataFromServerSQL()
//	{
//		return "";
//	}
//	/**
//	 * <p>
//	 * 从服务器取数据刷新业务员对应的普通客户信息的本地SqlLite表的数据.<br><br>
//	 * 
//	 * 注：本方法里不能涉及UI方面的任何操作——因为本方法很可能为提高用户体验而放置于一独立线程中运行，比如
//	 * 不应该使用AToolKits.queryData方法应该使用AToolKits.queryDataRoot，因为后
//	 * 者涉及到在出错时调用toast.<br><br>
//	 * 
//	 * <b>本方法中取的数据字段及字段顺序应与方法 {@link #insertRow(Vector)}中要解析的顺序严格一致！</b><br><br>
//	 * 
//	 * <b>注：</b>本方法中从服务端取数据的语句来自方法 {@link #getRefreshDataFromServerSQL()}，
//	 * 子类实现方法即可使用本方法自动刷新数据了.
//	 * </p>
//	 * @exception Exception 过程中出现的任何异常表示数据刷新不成功，否则表示更新成功
//	 * @see #getRefreshDataFromServerSQL()
//	 */
//	public void refreshDataFromServer() throws Exception
//	{
//		boolean updateSucess = true;
//		
//		//为确保缓存更新时代码的强壮性硬增加了一层异常处理
//		try
//		{
//			DataFromServer dfs = AToolKits.queryDataRoot(getRefreshDataFromServerSQL());
//			if(dfs.isSuccess())
//			{
//				Vector<Vector> data = (Vector<Vector>)dfs.getReturnValue();
//				this.deleteDatas();
//				this.insertRows(data);
//			}
//			else
//				updateSucess = false;
//		}
//		catch(Exception e)
//		{
//			updateSucess = false;
//			String es = "刷新客户信息的本地SqlLite缓存时出错，"+e.getMessage();
//			throw new EException(es, es, e.getCause());
//		}
//
//		if(!updateSucess)
//			throw new EException("刷新客户信息的本地SqlLite缓存时出错！");
//	}
}
